﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace Magenic.CodeMastery.SharePoint.PMO
{
    public class GanttPresenter
    {
        #region Private Fields

        private readonly GanttView View;
        private readonly int DayWidth = 25;
        private readonly int DayHeight = 25;
        private readonly int MonthHeight = 15;
        private readonly int BorderWidth = 1;

        #endregion

        #region Constructors

        public GanttPresenter(GanttView view)
        {
            this.View = view;
        }

        #endregion

        #region Public Methods

        public void LoadGanttChart(int year)
        {
            try
            {
                //TODO: DIP should be applied here:
                //GanttRepository repository = new ProjectRepository();
                ProjectRepository repository = new ProjectRepository();
                //TODO: Add overloaded GetProjects() to ProjectRepository
                IEnumerable<Project> projects = repository.GetProjectsOrderedForDisplay();
                
                if (!projects.Any())
                {
                    //TODO: Display projects not found message
                    return;
                }

                LoadCalendar(year);
                LoadActivities(year, projects);
                this.View.DataBind();
            }
            catch (Exception /*ex*/)
            {
                //TODO: An unhandled exception has occurred. Make sure the exception is logged and
                // a technical error message is displayed to the user.            
            }
        }

        #endregion

        #region Private Methods

        private void LoadCalendar(int year)
        {
            List<DateTime> dates = new List<DateTime>();
            for (int i = 1; i <= 12; i++)
            {
                DateTime date = new DateTime(year, i, 1);
                dates.Add(date);
            }

            LoadMonths(year, dates);
            LoadDays(year, dates);
        }

        private void LoadMonths(int year, List<DateTime> dates)
        {
            List<GanttBox> months = new List<GanttBox>();
            int left = 0;
            foreach (DateTime date in dates)
            {
                int daysInMonth = DateTime.DaysInMonth(year, date.Month);
                
                GanttBox month = new GanttBox();
                month.Text = date.ToString("Y");
                month.Width = daysInMonth * (DayWidth + BorderWidth) - BorderWidth;
                month.Left = left;
                month.Top = 0;
                months.Add(month);

                left += (month.Width + 1);
            }

            View.Months = months;
        }

        private void LoadDays(int year, List<DateTime> dates)
        {
            List<GanttBox> days = new List<GanttBox>();
            int left = 0;
            foreach (DateTime date in dates)
            {
                int daysInMonth = DateTime.DaysInMonth(year, date.Month);

                for (int i = 1; i <= daysInMonth; i++)
                { 
                    GanttBox day = new GanttBox();
                    day.Text = i.ToString();
                    day.Width = DayWidth;
                    day.Left = left;
                    day.Top = MonthHeight + 1;
                    days.Add(day);

                    left += (day.Width + 1);
                }
            }

            View.Days = days;
        }

        private void LoadActivities(int year, IEnumerable<Project> projects)
        {
            DateTime firstDayOfYear = new DateTime(year, 1, 1);
            DateTime lastDayOfYear = new DateTime(year, 12, 31);
            
            List<GanttBox> activities = new List<GanttBox>();
            int top = MonthHeight + DayHeight + (BorderWidth * 2) + 1;
            foreach (Project project in projects)
            {
                DateTime activityStart = project.Start >= firstDayOfYear ? project.Start : firstDayOfYear;
                DateTime activityFinish = project.Finish <= lastDayOfYear ? project.Finish : lastDayOfYear;
                TimeSpan duration = activityFinish - activityStart;
                int indent = (activityStart - firstDayOfYear).Days * (DayWidth + BorderWidth);

                GanttBox activity = new GanttBox();
                activity.Text = string.Format("{0} - {1}", project.Start.ToShortDateString(), project.Finish.ToShortDateString());
                activity.Width = duration.Days * (DayWidth + BorderWidth);
                activity.Left = indent;
                activity.Top = top;
                activities.Add(activity);

                top += (DayHeight + 1); 
            }

            View.Activities = activities;
        }

        #endregion
    }

    public class GanttBox
    {
        #region Constructors

        public GanttBox() { }

        #endregion

        #region Properties

        public string Text { get; set; }
        public int Width { get; set; }
        public int Top { get; set; }
        public int Left { get; set; }

        #endregion
    }
}
